package com.yanzhenjie.andserver.sample.controller.auth;

import android.util.Log;

import com.yanzhenjie.andserver.annotation.GetMapping;
import com.yanzhenjie.andserver.annotation.PostMapping;
import com.yanzhenjie.andserver.annotation.RequestBody;
import com.yanzhenjie.andserver.annotation.RequestMapping;
import com.yanzhenjie.andserver.annotation.RequestParam;
import com.yanzhenjie.andserver.annotation.RestController;
import com.yanzhenjie.andserver.http.HttpResponse;
import com.yanzhenjie.andserver.sample.SessionExpireManager;
import com.yanzhenjie.andserver.sample.controller.auth.dto.LoginDto;
import com.yanzhenjie.andserver.sample.controller.auth.vo.ChallengeVo;
import com.yanzhenjie.andserver.sample.controller.auth.vo.LoginVo;
import com.yanzhenjie.andserver.sample.controller.base.BaseController;
import com.yanzhenjie.andserver.sample.util.RandomUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;

/**
 * 作者: Tao
 * 日期: 2023/2/20
 * 时间: 16:24
 * 描述: 认证管理接口
 */
@RestController
@RequestMapping(path = "/api/auth")
public class AuthController extends BaseController {

    private static final String CLASS_NAME = "AuthController";
    public static final String CHALLENGE_PATH = "/api/auth/login/challenge";
    private static final String LOGIN_PATH = "/api/auth/login";

    private String challenge;
    private String salt;

    private int failTimes = 5;
    private long nextUnLockTime = 0L;
    private boolean isLocked = false;

    /**
     * 登录鉴权挑战
     */
    @GetMapping(path = "/login/challenge")
    Object challenge(HttpResponse response,
                     @RequestParam(name = "username", required = false) String username) {

        if (checkLocked()) {
            LoginVo loginVo = buildLoginVo();
            response.setStatus(401);
            return loginVo;
        }

        ChallengeVo res = new ChallengeVo();
        String id = RandomUtils.getRandom(32).toLowerCase();
        log("challenge--->sessionId = " + id);
        res.setSession_id(id);
        challenge = RandomUtils.getRandom(32).toLowerCase();
        res.setChallenge(challenge);
        salt = RandomUtils.getUUID();
        res.setSalt(salt);
        List<ChallengeVo.Link> links = new ArrayList<>();
        ChallengeVo.Link link = new ChallengeVo.Link();
        link.setRel("login");
        link.setHref(LOGIN_PATH);
        links.add(link);
        res.setLinks(links);

        log("challenge---> " + res);
        return res;
    }

    /**
     * 登录
     *
     * @param loginDto
     * @return
     */
    @PostMapping(path = "/login", produces = {"application/json"})
    LoginVo login(@RequestBody LoginDto loginDto) {

        if (checkLocked()) {
            return buildLoginVo();
        }

        LoginVo loginVo = new LoginVo();
        LoginVo.LockInfo lockInfo = new LoginVo.LockInfo();
        if (loginDto == null) {
            loginVo.setStatus(401);
            loginVo.setLock_info(lockInfo);
            return loginVo;
        }

        boolean isRight = true;
        int code = 200;
        String session_id = loginDto.getSession_id();
        String username = loginDto.getUsername();
        String password = loginDto.getPassword();
        /*判断必传字符传没*/
        if (StrUtil.isBlankIfStr(session_id) ||
                StrUtil.isBlankIfStr(username) ||
                StrUtil.isBlankIfStr(password)) {
            code = 401;
            isRight = false;
        }
        /*判断账号有没*/
        if (!username.equals("admin") && isRight) {
            code = 401;
            isRight = false;
        }
        /*判断密码有没*/
        log("login--->上传的密码为:" + password);
        String temp = "123456" + salt + challenge;
        String sha256Hex = DigestUtil.sha256Hex(temp);
        log("login--->现在的密码为:" + sha256Hex);
        if (!password.equals(sha256Hex) && isRight) {
            code = 401;
            isRight = false;
        }
        /*更新session*/
        SessionExpireManager.refreshExpired(session_id);

        loginVo.setStatus(code);
        if (code == 401) {
            if (failTimes == 0) {
                long time = new Date().getTime();
                nextUnLockTime = time + 30 * 60 * 1000;
                isLocked = true;
                lockInfo.setLocked(true);
                lockInfo.setUnlockTime((int) (nextUnLockTime - time));
            } else {
                lockInfo.setLocked(false);
                lockInfo.setRetry_time(failTimes);
                failTimes--;
            }
            loginVo.setLock_info(lockInfo);
        } else {
            failTimes = 5;
            isLocked = false;
            loginVo.setSession_id(session_id);
        }
        return loginVo;
    }

    /**
     * 检查是否被锁住
     */
    private boolean checkLocked() {
        if (isLocked && nextUnLockTime - new Date().getTime() > 0) {
            return true;
        } else if (isLocked && nextUnLockTime - new Date().getTime() <= 0) {
            return false;
        }
        return false;
    }

    /**
     * 构建锁住返回实体
     */
    private LoginVo buildLoginVo() {
        LoginVo loginVo = new LoginVo();
        LoginVo.LockInfo lockInfo = new LoginVo.LockInfo();
        lockInfo.setLocked(true);
        lockInfo.setUnlockTime((int) (nextUnLockTime - new Date().getTime()));
        loginVo.setStatus(401);
        loginVo.setLock_info(lockInfo);
        return loginVo;
    }

    @Override
    protected void log(String msg) {
        Log.i("AuthController", "AuthController--->" + msg);
    }
}
